package org.jppf.application.template;

import java.util.ArrayList;
import java.util.List;

import org.jppf.client.JPPFClient;
import org.jppf.client.JPPFConnectionPool;
import org.jppf.client.JPPFJob;
import org.jppf.client.Operator;
import org.jppf.node.protocol.Task;

public class TemplateApplicationRunner {

	public static void main(final String...args) {

		List<FractalConfig> list = GenFractal.genConfigs();

		try (JPPFClient jppfClient = new JPPFClient()) {
			System.out.println("Client Created: " + jppfClient.getUuid());

			TemplateApplicationRunner runner = new TemplateApplicationRunner();

			runner.executeMultipleConcurrentJobs(jppfClient, list);

		} catch(Exception e) {
			e.printStackTrace();
		}
	}


	public void executeMultipleConcurrentJobs(final JPPFClient jppfClient, List<FractalConfig> allConfigs) throws Exception {

		int numberOfMachines = 15;
		int numberOfJobs = numberOfMachines * 4;
		
		JPPFConnectionPool pool = jppfClient.awaitActiveConnectionPool();
		pool.setSize(numberOfMachines);
		pool.awaitActiveConnections(Operator.AT_LEAST, numberOfMachines);

		List<JPPFJob> jobList = new ArrayList<JPPFJob>();
		for(int i = 0; i < numberOfJobs; i++) {
			JPPFJob job = new JPPFJob();
			job.setBlocking(false);
			job.setName("Job: " + i);
			jobList.add(job);
		}

		int count = 0;
		for(FractalConfig config: allConfigs) {
			Task<?> task = jobList.get(count % (numberOfJobs)).add(new TemplateJPPFTask(config));
			task.setId("Task: " + config.id);
			count++;
		}
		
		for (JPPFJob job: jobList) {
			jppfClient.submitJob(job);
		}

		System.out.println("Executing Jobs ...");

		for (JPPFJob job: jobList) {
			List<Task<?>> results = job.awaitResults();
			processExecutionResults(job.getName(), results);
		}
		
//		JPPFJob job = new JPPFJob();
//		job.setBlocking(false);
//		job.setName("Job: ");
//		List<FractalConfig> list = GenFractal.genConfigs();
//		Task<?> task = job.add(new TemplateJPPFTask(list.get(0)));
//		task.setId("Task: " + list.get(0).id);
//		jppfClient.submitJob(job);
//		List<Task<?>> results = job.awaitResults();
//		processExecutionResults(job.getName(), results);
		
	}

	public synchronized void processExecutionResults(final String jobName, final List<Task<?>> results) {
		// print a results header
		System.out.printf("Results for job '%s' :\n", jobName);
		// process the results
		for (Task<?> task: results) {
			String taskName = task.getId();
			
			if (task.getThrowable() == null) {
				System.out.println(taskName + ", execution result: " + task.getResult());
			} else {
				System.out.println(taskName + ", an exception was raised: " + task.getThrowable().getMessage());
			}
		}
	}
}
